package com.git.hui.yinshua.biz.order.service;

import com.alibaba.fastjson.JSONObject;
import com.git.hui.yinshua.api.model.ExceptionUtil;
import com.git.hui.yinshua.api.model.Status;
import com.git.hui.yinshua.api.model.order.OrderStatusEnum;
import com.git.hui.yinshua.api.model.order.OrderTypeEnum;
import com.git.hui.yinshua.api.model.order.PtOrderStatusEnum;
import com.git.hui.yinshua.biz.goods.service.GoodsService;
import com.git.hui.yinshua.biz.order.dao.entity.OrderEntity;
import com.git.hui.yinshua.biz.order.dao.entity.OrderItemEntity;
import com.git.hui.yinshua.biz.order.dao.entity.PtOrderEntity;
import com.git.hui.yinshua.biz.order.dao.repository.OrderRepository;
import com.git.hui.yinshua.biz.order.dao.repository.PtOrderRepository;
import com.git.hui.yinshua.biz.pay.service.PaymentService;
import com.git.hui.yinshua.biz.rest.models.goods.rsp.GoodsInfoDto;
import com.git.hui.yinshua.biz.rest.models.goods.rsp.GoodsSpecDto;
import com.git.hui.yinshua.biz.rest.models.order.req.OrderCreateReq;
import com.git.hui.yinshua.biz.rest.models.order.req.OrderItemCreateReq;
import com.git.hui.yinshua.biz.util.ImgUtil;
import com.git.hui.yinshua.biz.util.PriceUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author YiHui
 * @date 2024/6/20
 */
@Slf4j
@Service
public class AppOrderService {
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private PtOrderRepository ptOrderRepository;

    @Autowired
    private GoodsService goodsService;
    @Autowired
    private PtOrderService ptOrderService;
    @Autowired
    private PaymentService paymentService;

    /**
     * 下单
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Long createOrder(OrderCreateReq req) {
        Integer goodsId = req.getItemList().get(0).getGoodsId();
        GoodsInfoDto goods = goodsService.queryGoodsDetail(goodsId);

        // 更新商品对应的价格
        this.updateGoodsPrice(goods, req);
        this.checkOrderPrice(req);

        // 保存订单
        OrderEntity order = orderRepository.addOrder(req);
        orderRepository.addOrderItems(order, req);
        return order.getId();
    }

    /**
     * 拼团订单
     *
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Long createPtOrder(OrderCreateReq req) {
        Integer goodsId = req.getItemList().get(0).getGoodsId();
        GoodsInfoDto goods = goodsService.queryGoodsDetail(goodsId);
        if (req.getPtOrderId() == null) {
            // 开团
            // 1. 保存订单
            OrderEntity order = this.saveOrder(goods, req);
            req.setOrderId(order.getId());
            // 2. 创建拼团订单
            PtOrderEntity ptOrder = ptOrderRepository.addOrder(goods, req);
            req.setPtOrderId(ptOrder.getId());
            // 3. 保存用户参团记录
            ptOrderRepository.addOrderItem(req);
            return order.getId();
        } else {
            // 1. 参团，先加锁，避免出现参团人员超过限制的情况
            PtOrderEntity ptOrder = ptOrderRepository.queryPtOrderForLock(req.getPtOrderId());
            if (ptOrder == null || PtOrderStatusEnum.FAILED.getStatus().equals(ptOrder.getPtStatus())) {
                throw ExceptionUtil.of(Status.StatusEnum.BIZ_EXCEPTION, "当前团不可用，请换一个团下单吧~");
            }

            if (ptOrder.getEndTime().getTime() < System.currentTimeMillis()) {
                // 团已经结束了
                ptOrderService.autoClosePtOrder(ptOrder.getId());
                throw ExceptionUtil.of(Status.StatusEnum.BIZ_EXCEPTION, "当前团不可用，请换一个团下单吧~");
            }

            // 2. 判断是否可以成团：
            if (ptOrderService.ptNumOver(ptOrder)) {
                throw ExceptionUtil.of(Status.StatusEnum.BIZ_EXCEPTION, "当前团已经满员了，换一个团参加吧~");
            }

            // 3. 保存订单
            OrderEntity order = this.saveOrder(goods, req);
            req.setOrderId(order.getId());
            // 4. 保存用户参团记录
            ptOrderRepository.addOrderItem(req);
            return order.getId();
        }
    }

    private OrderEntity saveOrder(GoodsInfoDto goods, OrderCreateReq req) {
        // 更新商品对应的价格
        this.updateGoodsPrice(goods, req);
        this.checkOrderPrice(req);

        // 保存订单
        OrderEntity order = orderRepository.addOrder(req);
        List<OrderItemEntity> itemList = orderRepository.addOrderItems(order, req);
        order.setOrderItemList(itemList);

        // 更新商品销量
        req.getItemList().forEach(item -> {
            goodsService.updateGoodsSales(item.getGoodsId(), item.getBuyCnt());
        });
        return order;
    }

    /**
     * 商品相关的信息，直接从db中进行补齐
     *
     * @param goods
     * @param req
     */
    private void updateGoodsPrice(GoodsInfoDto goods, OrderCreateReq req) {
        if (CollectionUtils.isEmpty(goods.getSpecList())) {
            // 无尺寸规格时，下单的商品信息，使用 goods 的数据进行补齐
            req.getItemList().forEach(item -> {
                if (item.getOrderQuantity() < goods.getMinCnt()) {
                    throw ExceptionUtil.of(Status.StatusEnum.ILLEGAL_ARGUMENTS_MIXED, "下单数量小于起售数量");
                }
                // 原价
                item.setGoodsPrice(goods.getPrice());
                if (BooleanUtils.isTrue(req.getPtGoods()) && Objects.equals(req.getType(), OrderTypeEnum.NORMAL.getType())) {
                    // 拼团商品，直接购买
                    item.setOrderPrice(goods.getPrice());
                } else {
                    // 折扣价
                    item.setOrderPrice(PriceUtil.legalPrice(goods.getDiscountPrice()) ? goods.getDiscountPrice() : goods.getPrice());
                }
                item.setGoodsName(goods.getName());
                item.setGoodsIntro(goods.getIntro());
                item.setGoodsThumb(ImgUtil.toImgs(goods.getThumbs()));
                item.setSpecId(null);
                item.setSpec("");
            });
        } else {
            // 下单的商品信息，使用db中的数据进行补齐
            Map<Integer, GoodsSpecDto> specMap = goods.getSpecList().stream().collect(Collectors.toMap(GoodsSpecDto::getSpecId, s -> s));
            req.getItemList().forEach(item -> {
                GoodsSpecDto spec = specMap.get(item.getSpecId());
                if (spec == null) {
                    throw ExceptionUtil.of(Status.StatusEnum.ILLEGAL_ARGUMENTS_MIXED, "选择的商品不对!");
                }

                if (item.getOrderQuantity() < spec.getMinCnt()) {
                    throw ExceptionUtil.of(Status.StatusEnum.ILLEGAL_ARGUMENTS_MIXED, "下单数量小于起售数量");
                }
                // 原价
                item.setGoodsPrice(spec.getPrice());
                if (BooleanUtils.isTrue(req.getPtGoods()) && Objects.equals(req.getType(), OrderTypeEnum.NORMAL.getType())) {
                    // 拼团商品，直接购买
                    item.setOrderPrice(spec.getPrice());
                } else {
                    // 折扣价
                    item.setOrderPrice(PriceUtil.legalPrice(spec.getDiscountPrice()) ? spec.getDiscountPrice() : spec.getPrice());
                }
                item.setSpecId(spec.getSpecId());
                item.setGoodsId(goods.getGoodsId());
                item.setGoodsName(goods.getName());
                item.setGoodsIntro(goods.getIntro());
                item.setGoodsThumb(ImgUtil.toImgs(goods.getThumbs()));
                item.setSpec(spec.getSpec());
            });
        }
    }

    /**
     * 订单金额校对
     *
     * @param req
     */
    private void checkOrderPrice(OrderCreateReq req) {
        Integer reqShipping = PriceUtil.toCentPrice(req.getShippingAmount());
        if (reqShipping == null) {
            reqShipping = 0;
            req.setShippingAmount("0");
        }

        // 订单原始金额
        AtomicReference<Integer> totalOriginalPrice = new AtomicReference<>(reqShipping);
        // 订单实际支付金额
        AtomicReference<Integer> totalOrderPrice = new AtomicReference<>(reqShipping);
        req.getItemList().forEach(item -> {
            // 原价
            Integer cent = PriceUtil.toCentPrice(item.getGoodsPrice());
            totalOriginalPrice.updateAndGet(v -> v + cent * item.getOrderQuantity());

            // 下单单价
            Integer orderCent = PriceUtil.toCentPrice(item.getOrderPrice());
            totalOrderPrice.updateAndGet(v -> v + orderCent * item.getOrderQuantity());
        });


        // 订单原价对比
        Integer reqOriginalAmount = PriceUtil.toCentPrice(req.getOriginalAmount());
        if (!Objects.equals(totalOriginalPrice.get(), reqOriginalAmount)) {
            throw ExceptionUtil.of(Status.StatusEnum.ILLEGAL_ARGUMENTS_MIXED, "下单订单总金额不对");
        }

        // 订单金额对比
        Integer reqOrderAmount = PriceUtil.toCentPrice(req.getOrderAmount());
        if (!Objects.equals(reqOrderAmount, totalOrderPrice.get())) {
            log.info("下单支付金额校验失败: {} != {}, req={}", reqOrderAmount, totalOrderPrice, JSONObject.toJSONString(req));
            throw ExceptionUtil.of(Status.StatusEnum.ILLEGAL_ARGUMENTS_MIXED, "下单支付金额不对");
        }

        // fixme 这里直接将支付金额设置为订单金额
        req.setPayAmount(req.getOrderAmount());
    }

    /**
     * 更新订单信息
     *
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOrderInfo(OrderCreateReq req) {
        OrderEntity order = orderRepository.querySimpleOrderForUpdate(req.getOrderId());
        if (StringUtils.isNotBlank(req.getReceivingAddress())) {
            // 表示更新收货地址
            if (order.getOrderStatus() > OrderStatusEnum.TO_PRINT.getStatus()) {
                // 如果图片已经下载，准备打印了，此时不允许修改地址
                throw ExceptionUtil.of(Status.StatusEnum.BIZ_EXCEPTION, "备货中啦，不再支持修改收货地址了哦~");
            }

            return this.updateOrderReceiveAddress(req, order);
        } else if (!CollectionUtils.isEmpty(req.getItemList())) {
            // 表示更新订单明细的图片
            if (order.getOrderStatus() > OrderStatusEnum.TO_PRINT.getStatus()) {
                // 如果图片已经下载，准备打印了，此时不允许修改地址
                throw ExceptionUtil.of(Status.StatusEnum.BIZ_EXCEPTION, "备货中啦，不再支持重新传图了哦~");
            }

            return this.updateOrderDetailUploadImgs(req);
        }
        return true;
    }


    /**
     * 更新用户收货地址
     *
     * @param req
     * @param order
     * @return
     */
    private boolean updateOrderReceiveAddress(OrderCreateReq req, OrderEntity order) {
        order.setReceivingAddress(req.getReceivingAddress());
        order.setReceivingPerson(req.getReceivingPerson());
        order.setReceivingArea(req.getReceivingArea());
        order.setReceivingPhone(req.getReceivingPhone());
        return orderRepository.updateReceiveInfo(order);
    }

    /**
     * 更新用户上传的图片
     *
     * @param req
     * @return
     */
    private boolean updateOrderDetailUploadImgs(OrderCreateReq req) {
        List<OrderItemCreateReq> items = req.getItemList();
        for (OrderItemCreateReq item : items) {
            if (!orderRepository.updateOrderDetailImgs(item.getDetailId(), ImgUtil.toImgs(item.getOriginalImgs()), ImgUtil.toImgs(item.getUploadImgs()))) {
                throw ExceptionUtil.of(Status.StatusEnum.BIZ_EXCEPTION, "图片更新失败!");
            }
        }
        return true;
    }

}
